Extract Apical progenitors and compute Pseudo-DorsoVentral score

Extract apical progenitors and filter the gene expression matrix

We perform Kmeans clustering on the 2 cell state scores :

  • Apical progenitors AP
  • Basal progenitors BP

We then extract the glutamatergic neuron branche as beeing the Kmeans cluster with the highest mean Apical progenitor signature

Import Spring dimensionality reduction

Cell cycle associated genes were excluded for PCA dimensionality reduction and Spring plot was generating with these parameter :

Number of cells: 1648
Number of genes that passed filter: 857
Min expressing cells (gene filtering): 3
Min number of UMIs (gene filtering): 3
Gene variability %ile (gene filtering): 90
Number of principal components: 7
Number of nearest neighbors: 20
Number of force layout iterations: 500

Fit a principal curve over the AP in the Spring space

## Starting curve---distance^2: 2022449778
## Iteration 1---distance^2: 745172
## Iteration 2---distance^2: 696270.5
## Iteration 3---distance^2: 677509.1
## Iteration 4---distance^2: 668251.7
## Iteration 5---distance^2: 663393.6
## Iteration 6---distance^2: 660928.6
## Iteration 7---distance^2: 659586.4
## Iteration 8---distance^2: 658917.8
## Iteration 9---distance^2: 658638.8

Manuscript Fig. 5A

Manuscript Fig. 5A

Find differentially expressed genes along the pseudo DV axis

Cluster gene by similar profiles over pseudo-DV axis

Assign domain identity

We assign domain identity based on clusters’ transcriptional profile by setting boundaries over pseudo-dv score

Manuscript Fig. 5D

Manuscript Fig. 5D

Transfert these ident on the full dataset (Manuscript Fig. 2A)

## [1] "Cluster_Sub.Pallium.2: 363 Cells"
## [1] "Cluster_Ventral.Pallium: 312 Cells"
## [1] "Cluster_Sub.Pallium.3: 197 Cells"
## [1] "Cluster_lateral.Pallium.1: 219 Cells"
## [1] "Cluster_Dorsal.Pallium: 201 Cells"
## [1] "Cluster_lateral.Pallium.2: 113 Cells"
## [1] "Cluster_Sub.Pallium.1: 241 Cells"
Manuscript Fig. 2A

Manuscript Fig. 2A

Session Info

## [1] "05 novembre, 2020, 18,16"
## R version 3.6.3 (2020-02-29)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Ubuntu 18.04.5 LTS
## 
## Matrix products: default
## BLAS:   /usr/lib/x86_64-linux-gnu/atlas/libblas.so.3.10.3
## LAPACK: /usr/lib/x86_64-linux-gnu/atlas/liblapack.so.3.10.3
## 
## locale:
##  [1] LC_CTYPE=fr_FR.UTF-8       LC_NUMERIC=C              
##  [3] LC_TIME=fr_FR.UTF-8        LC_COLLATE=fr_FR.UTF-8    
##  [5] LC_MONETARY=fr_FR.UTF-8    LC_MESSAGES=fr_FR.UTF-8   
##  [7] LC_PAPER=fr_FR.UTF-8       LC_NAME=C                 
##  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
## [11] LC_MEASUREMENT=fr_FR.UTF-8 LC_IDENTIFICATION=C       
## 
## attached base packages:
##  [1] splines   stats4    parallel  stats     graphics  grDevices utils    
##  [8] datasets  methods   base     
## 
## other attached packages:
##  [1] viridis_0.5.1       viridisLite_0.3.0   wesanderson_0.3.6  
##  [4] RColorBrewer_1.1-2  gridExtra_2.3       reshape_0.8.8      
##  [7] dplyr_0.8.3         ggExtra_0.9         cluster_2.1.0      
## [10] princurve_2.1.4     monocle_2.14.0      DDRTree_0.1.5      
## [13] irlba_2.3.3         VGAM_1.1-2          Biobase_2.46.0     
## [16] BiocGenerics_0.32.0 Seurat_2.3.4        Matrix_1.2-17      
## [19] cowplot_1.0.0       ggplot2_3.2.1      
## 
## loaded via a namespace (and not attached):
##   [1] snow_0.4-3           backports_1.1.5      Hmisc_4.3-0         
##   [4] plyr_1.8.4           igraph_1.2.5         lazyeval_0.2.2      
##   [7] densityClust_0.3     fastICA_1.2-2        digest_0.6.25       
##  [10] foreach_1.4.7        htmltools_0.5.0      lars_1.2            
##  [13] gdata_2.18.0         magrittr_1.5         checkmate_1.9.4     
##  [16] gclus_1.3.2          mixtools_1.1.0       ROCR_1.0-7          
##  [19] limma_3.42.0         matrixStats_0.55.0   R.utils_2.9.0       
##  [22] docopt_0.6.1         colorspace_1.4-1     ggrepel_0.8.1       
##  [25] xfun_0.18            sparsesvd_0.2        crayon_1.3.4        
##  [28] jsonlite_1.7.0       zeallot_0.1.0        survival_2.44-1.1   
##  [31] zoo_1.8-6            iterators_1.0.12     ape_5.3             
##  [34] glue_1.4.1           registry_0.5-1       gtable_0.3.0        
##  [37] kernlab_0.9-29       prabclus_2.3-1       DEoptimR_1.0-8      
##  [40] scales_1.1.0         pheatmap_1.0.12      bibtex_0.4.2        
##  [43] miniUI_0.1.1.1       Rcpp_1.0.5           metap_1.1           
##  [46] dtw_1.21-3           xtable_1.8-4         htmlTable_1.13.2    
##  [49] reticulate_1.13      foreign_0.8-72       bit_4.0.4           
##  [52] proxy_0.4-23         mclust_5.4.5         SDMTools_1.1-221.1  
##  [55] Formula_1.2-3        tsne_0.1-3           htmlwidgets_1.5.1   
##  [58] httr_1.4.1           FNN_1.1.3            gplots_3.0.1.1      
##  [61] fpc_2.2-3            acepack_1.4.1        modeltools_0.2-22   
##  [64] ica_1.0-2            farver_2.0.1         pkgconfig_2.0.3     
##  [67] R.methodsS3_1.7.1    flexmix_2.3-15       nnet_7.3-14         
##  [70] labeling_0.3         tidyselect_0.2.5     rlang_0.4.7         
##  [73] reshape2_1.4.3       later_1.0.0          munsell_0.5.0       
##  [76] tools_3.6.3          ggridges_0.5.1       fastmap_1.0.1       
##  [79] evaluate_0.14        stringr_1.4.0        yaml_2.2.1          
##  [82] npsurv_0.4-0         knitr_1.26           bit64_4.0.2         
##  [85] fitdistrplus_1.0-14  robustbase_0.93-5    caTools_1.17.1.2    
##  [88] purrr_0.3.3          RANN_2.6.1           dendextend_1.12.0   
##  [91] pbapply_1.4-2        nlme_3.1-141         mime_0.7            
##  [94] slam_0.1-46          R.oo_1.23.0          hdf5r_1.3.2.9000    
##  [97] compiler_3.6.3       rstudioapi_0.11      png_0.1-7           
## [100] lsei_1.2-0           tibble_2.1.3         stringi_1.4.6       
## [103] highr_0.8            lattice_0.20-41      HSMMSingleCell_1.6.0
## [106] vctrs_0.2.0          pillar_1.4.2         lifecycle_0.1.0     
## [109] combinat_0.0-8       Rdpack_0.11-0        lmtest_0.9-37       
## [112] data.table_1.12.6    bitops_1.0-6         seriation_1.2-9     
## [115] gbRd_0.4-11          httpuv_1.5.2         R6_2.4.1            
## [118] latticeExtra_0.6-28  TSP_1.1-10           promises_1.1.0      
## [121] KernSmooth_2.23-15   codetools_0.2-16     MASS_7.3-53         
## [124] gtools_3.8.1         assertthat_0.2.1     withr_2.1.2         
## [127] qlcMatrix_0.9.7      mgcv_1.8-33          diptest_0.75-7      
## [130] doSNOW_1.0.18        grid_3.6.3           rpart_4.1-15        
## [133] tidyr_1.0.0          class_7.3-17         rmarkdown_2.5       
## [136] segmented_1.0-0      Rtsne_0.15           shiny_1.4.0         
## [139] base64enc_0.1-3

  1. Institute of Psychiatry and Neuroscience of Paris, INSERM U1266, 75014, Paris, France

LS0tCnRpdGxlOiAiSW52ZXN0aWdhdGlvbiBvZiB0aGUgYXBpY2FsIHByb2dlbml0b3JzIGRpdmVyc2l0eSIKYXV0aG9yOgogIC0gTWF0dGhpZXUgTW9yZWF1XltJbnN0aXR1dGUgb2YgUHN5Y2hpYXRyeSBhbmQgTmV1cm9zY2llbmNlIG9mIFBhcmlzLCBJTlNFUk0gVTEyNjYsIDc1MDE0LCBQYXJpcywgRnJhbmNlXSwgbWF0dGhpZXUubW9yZWF1QGluc2VybS5mcgpkYXRlOiAiYHIgZm9ybWF0KFN5cy50aW1lKCksICclZCAlQiwgJVknKWAiCm91dHB1dDogCiAgaHRtbF9kb2N1bWVudDogCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMKICAgIGRmX3ByaW50OiB0aWJibGUKICAgIGhpZ2hsaWdodDogaGFkZG9jawogICAgaW5jbHVkZXM6CiAgICAgIGluX2hlYWRlcjogaGVhZGVyLmh0bWwKICAgIHRoZW1lOiBjb3NtbwogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogNQogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IHllcwotLS0KCmBgYHtjc3MsIGVjaG89RkFMU0V9CmgxIHsKICBmb250LXNpemU6IDM0cHg7CiAgbWFyZ2luLXRvcDogMnJlbTsKICBtYXJnaW4tYm90dG9tOiAxcmVtOwogIGNvbG9yOiAjZTY0ZDAwOwogIHRleHQtZGVjb3JhdGlvbjogbm9uZTsKfQpoMS50aXRsZSB7CiAgZm9udC1zaXplOiA0MHB4OwogIG1hcmdpbi10b3A6IDJyZW07CiAgbWFyZ2luLWJvdHRvbTogMXJlbTsKICB0ZXh0LWFsaWduOiBjZW50ZXI7CiAgdGV4dC1kZWNvcmF0aW9uOiBub25lOwogIGNvbG9yOiAjMDAwMDAwOwp9CmgyIHsKICBmb250LXNpemU6IDMwcHg7CiAgbWFyZ2luLXRvcDogMnJlbTsKICBtYXJnaW4tYm90dG9tOiAxcmVtOwogIGNvbG9yOiAjMDAwMDAwOwp9CmgzIHsKICBmb250LXNpemU6IDI0cHg7CiAgbWFyZ2luLXRvcDogMnJlbTsKICBtYXJnaW4tYm90dG9tOiAxcmVtOwogIGNvbG9yOiAjMDAwMDAwOwp9Cmg0IHsKICBmb250LXNpemU6IDIwcHg7CiAgbWFyZ2luLXRvcDogMnJlbTsKICBtYXJnaW4tYm90dG9tOiAxcmVtOwogIGNvbG9yOiAjMDAwMDAwOwp9Cmg1IHsKICBmb250LXNpemU6IDE4cHg7CiAgbWFyZ2luLXRvcDogMnJlbTsKICBtYXJnaW4tYm90dG9tOiAxcmVtOwogIGNvbG9yOiAjMDAwMDAwOwp9Cgouc2Nyb2xsLTEwMCB7CiAgbWF4LWhlaWdodDogMjAwcHg7CiAgb3ZlcmZsb3cteTogYXV0bzsKICBiYWNrZ3JvdW5kLWNvbG9yOiBpbmhlcml0Owp9CgpwIHsKICBmb250LXNpemU6IDE2cHg7Cn0KYGBgCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCBmaWcuYWxpZ24gPSAnY2VudGVyJywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSkKYGBgCgojIExvYWQgbGlicmFyaWVzIGFuZCBRQ0ZpbHRlcmVkIGRhdGFzZXQKCmBgYHtyIH0KIyBMb2FkIGxpYnJhcnkKbGlicmFyeShTZXVyYXQpCmxpYnJhcnkobW9ub2NsZSkKbGlicmFyeShwcmluY3VydmUpCmxpYnJhcnkoY2x1c3RlcikKbGlicmFyeShwYXJhbGxlbCkKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGdnRXh0cmEpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkocmVzaGFwZSkKbGlicmFyeShncmlkRXh0cmEpCmxpYnJhcnkoUkNvbG9yQnJld2VyKQpsaWJyYXJ5KHdlc2FuZGVyc29uKQpsaWJyYXJ5KHZpcmlkaXMpCgojU2V0IGdncGxvdCB0aGVtZSBhcyBjbGFzc2ljCnRoZW1lX3NldCh0aGVtZV9jbGFzc2ljKCkpCmBgYAoKYGBge3J9CiMgTG9hZCB0aGUgZnVsbCBhbm5vdGF0ZWQgZGF0YXNldApBbGxjZWxscy5kYXRhIDwtIHJlYWRSRFMoIi4vUUMuZmlsdGVyZWQuY2VsbHMuUkRTIikKYGBgCgojIEV4dHJhY3QgQXBpY2FsIHByb2dlbml0b3JzIGFuZCBjb21wdXRlIFBzZXVkby1Eb3Jzb1ZlbnRyYWwgc2NvcmUKCiMjIEV4dHJhY3QgYXBpY2FsIHByb2dlbml0b3JzIGFuZCBmaWx0ZXIgdGhlIGdlbmUgZXhwcmVzc2lvbiBtYXRyaXgKCldlIHBlcmZvcm0gS21lYW5zIGNsdXN0ZXJpbmcgb24gdGhlIDIgY2VsbCBzdGF0ZSBzY29yZXMgOgoKLSBBcGljYWwgcHJvZ2VuaXRvcnMgYEFQYAotIEJhc2FsIHByb2dlbml0b3JzIGBCUGAKCmBgYHtyIH0Kc2V0LnNlZWQoMTAwKQojSy1tZWFucyBjbHVzdGVyaW5nIGJhc2VkIG9uIEFQLCBCUCBzY29yZXMgYWNyb3NzIGNlbGxzCmNsIDwtIGttZWFucyhjYmluZChBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSRBUF9zaWduYXR1cmUxLCBBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSRCUF9zaWduYXR1cmUxKSwgMykKQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEka21lYW5DbHVzdCA8LSBwYXN0ZTAoIkNsdXN0LiIsY2wkY2x1c3RlcikKYGBgCgoKYGBge3IgZmlnLmRpbT1jKDUuMywgNCl9CmNvbC5wYWwgPC0gd2VzX3BhbGV0dGUoIkdyYW5kQnVkYXBlc3QxIiwgMywgdHlwZSA9ICJkaXNjcmV0ZSIpCgpwMSA8LSBnZ3Bsb3QoQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEsIGFlcyh4PUFQX3NpZ25hdHVyZTEsIHk9QlBfc2lnbmF0dXJlMSwgY29sb3VyID0ga21lYW5DbHVzdCkpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWNvbC5wYWwpICsKICBnZW9tX3BvaW50KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKQpnZ01hcmdpbmFsKHAxLCB0eXBlID0gImhpc3RvZ3JhbSIsIGZpbGw9ImxpZ2h0Z3JleSIpIDsgcm0ocDEpCgpEaW1QbG90KEFsbGNlbGxzLmRhdGEsCiAgICAgICAgZ3JvdXAuYnkgPSAia21lYW5DbHVzdCIsCiAgICAgICAgcmVkdWN0aW9uLnVzZSA9ICJzcHJpbmciLAogICAgICAgIGNvbHMudXNlID0gY29sLnBhbCwKICAgICAgICBkaW0uMSA9IDEsCiAgICAgICAgZGltLjIgPSAyLAogICAgICAgIGRvLmxhYmVsPVQsCiAgICAgICAgbGFiZWwuc2l6ZSA9IDQsCiAgICAgICAgbm8ubGVnZW5kID0gRikKYGBgCgpXZSB0aGVuIGV4dHJhY3QgdGhlIGdsdXRhbWF0ZXJnaWMgbmV1cm9uIGJyYW5jaGUgYXMgYmVlaW5nIHRoZSBLbWVhbnMgY2x1c3RlciB3aXRoIHRoZSBoaWdoZXN0IG1lYW4gYEFwaWNhbCBwcm9nZW5pdG9yYCBzaWduYXR1cmUKCmBgYHtyIGZpZy5kaW09Yyg1LjMsIDQpfQojRmluIGNsdXN0ZXIgd2lodCB0aGUgaGlnaGVzdCBtZWFuIEFQc2NvcmUKTWVhbktjbHVzdC5BUHNjb3JlIDwtIGFnZ3JlZ2F0ZShBUF9zaWduYXR1cmUxIH4ga21lYW5DbHVzdCwgQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEsIG1lYW4pCkFQY2x1c3QgPC0gTWVhbktjbHVzdC5BUHNjb3JlICU+JSBmaWx0ZXIoQVBfc2lnbmF0dXJlMSA9PSBtYXgoQVBfc2lnbmF0dXJlMSkpICU+JSBwdWxsKGttZWFuQ2x1c3QpCgojRXh0cmFjdCBhcGljYWwgcHJvZ2VuaXRvcnMgCmJhcmNvZGVzIDwtIEFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhICU+JSBmaWx0ZXIoa21lYW5DbHVzdCA9PSBBUGNsdXN0KSAlPiUgcHVsbChCYXJjb2RlcykKQVAuZGF0YSA8LSAgU3Vic2V0RGF0YShBbGxjZWxscy5kYXRhLCBjZWxscy51c2UgPSBiYXJjb2RlcyAsIHN1YnNldC5yYXcgPSBULCAgZG8uY2xlYW4gPSBGKQoKI0Z1cnRoZXIgZmlsdGVyIHRoZSAzIG91dGxpZXIgY2VsbHMgYmFzZWQgb24gc3ByaW5nIGNvb3JkaW5hdGVzCmNlbGxzIDwtIHJvd25hbWVzKEFQLmRhdGFAZHIkc3ByaW5nQGNlbGwuZW1iZWRkaW5nc1tBUC5kYXRhQGRyJHNwcmluZ0BjZWxsLmVtYmVkZGluZ3NbLDJdID4gMjUwLF0pCkFQLmRhdGEgPC0gIFN1YnNldERhdGEoQVAuZGF0YSwgY2VsbHMudXNlID0gY2VsbHMgLCBzdWJzZXQucmF3ID0gVCwgIGRvLmNsZWFuID0gRikKCkRpbVBsb3QoQVAuZGF0YSwKICAgICAgICBncm91cC5ieSA9ICJrbWVhbkNsdXN0IiwKICAgICAgICByZWR1Y3Rpb24udXNlID0gInNwcmluZyIsCiAgICAgICAgY29scy51c2UgPSBjb2wucGFsLAogICAgICAgIGRpbS4xID0gMSwKICAgICAgICBkaW0uMiA9IDIsCiAgICAgICAgZG8ubGFiZWw9VCwKICAgICAgICBsYWJlbC5zaXplID0gNCwKICAgICAgICBuby5sZWdlbmQgPSBGKQpgYGAKCiMjIEZpbHRlciBnZW5lIGNvdW50cyBtYXRyaXgKCmBgYHtyfQojUmVtb3ZlIG5vbiBlcHJlc3NlZCBnZW5lcwpudW0uY2VsbHMgPC0gTWF0cml4Ojpyb3dTdW1zKEFQLmRhdGFAZGF0YSA+IDApCmdlbmVzLnVzZSA8LSBuYW1lcyh4ID0gbnVtLmNlbGxzW3doaWNoKHggPSBudW0uY2VsbHMgPj0gMjApXSkKQVAuZGF0YUByYXcuZGF0YSA8LSBBUC5kYXRhQHJhdy5kYXRhW2dlbmVzLnVzZSwgXQpBUC5kYXRhQGRhdGEgPC0gQVAuZGF0YUBkYXRhW2dlbmVzLnVzZSwgXQoKI05vcm1hbGl6ZSBhbmQgU2NhbGUgdGhlIGRhdGEKQVAuZGF0YSA8LSBOb3JtYWxpemVEYXRhKG9iamVjdCA9IEFQLmRhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICBub3JtYWxpemF0aW9uLm1ldGhvZCA9ICJMb2dOb3JtYWxpemUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlLmZhY3RvciA9IHJvdW5kKG1lZGlhbihBUC5kYXRhQG1ldGEuZGF0YSRuVU1JKSksCiAgICAgICAgICAgICAgICAgICAgICAgICBkaXNwbGF5LnByb2dyZXNzID0gRikKCkFQLmRhdGEgPC0gRmluZFZhcmlhYmxlR2VuZXMob2JqZWN0ID0gQVAuZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lYW4uZnVuY3Rpb24gPSBFeHBNZWFuLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzcGVyc2lvbi5mdW5jdGlvbiA9IExvZ1ZNUiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHgubG93LmN1dG9mZiA9IDAuMDEyNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHguaGlnaC5jdXRvZmYgPSAzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeS5jdXRvZmYgPSAxLCBkby5wbG90ID0gRiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3BsYXkucHJvZ3Jlc3MgPSBGKQoKQVAuZGF0YSA8LSBTY2FsZURhdGEob2JqZWN0ID0gQVAuZGF0YSwgdmFycy50by5yZWdyZXNzID0gYygiQ0MuRGlmZmVyZW5jZSIsInBlcmNlbnQubWl0byIsICJuVU1JIiksIGRpc3BsYXkucHJvZ3Jlc3MgPSBGKQpgYGAKCiMjIEltcG9ydCBTcHJpbmcgZGltZW5zaW9uYWxpdHkgcmVkdWN0aW9uCgoqKkNlbGwgY3ljbGUgYXNzb2NpYXRlZCBnZW5lcyoqIHdlcmUgZXhjbHVkZWQgZm9yIFBDQSBkaW1lbnNpb25hbGl0eSByZWR1Y3Rpb24gYW5kIFNwcmluZyBwbG90IHdhcyBnZW5lcmF0aW5nIHdpdGggdGhlc2UgcGFyYW1ldGVyIDoKCmBgYApOdW1iZXIgb2YgY2VsbHM6IDE2NDgKTnVtYmVyIG9mIGdlbmVzIHRoYXQgcGFzc2VkIGZpbHRlcjogODU3Ck1pbiBleHByZXNzaW5nIGNlbGxzIChnZW5lIGZpbHRlcmluZyk6IDMKTWluIG51bWJlciBvZiBVTUlzIChnZW5lIGZpbHRlcmluZyk6IDMKR2VuZSB2YXJpYWJpbGl0eSAlaWxlIChnZW5lIGZpbHRlcmluZyk6IDkwCk51bWJlciBvZiBwcmluY2lwYWwgY29tcG9uZW50czogNwpOdW1iZXIgb2YgbmVhcmVzdCBuZWlnaGJvcnM6IDIwCk51bWJlciBvZiBmb3JjZSBsYXlvdXQgaXRlcmF0aW9uczogNTAwCmBgYAoKYGBge3J9CiNJbXBvcnQgU3ByaW5nIGNvb3JkaW5hdGVzIGNhbGN1bGF0ZWQgd2l0aG91dCBjZWxsIGN5Y2xlIGdlbmVzCkNvb3JkaW5hdGVzIDwtIHJlYWQudGFibGUoIi4vUHJvZ2VuaXRvcnMvRTEyLkFQLkNvb3JkaW5hdGVzLnR4dCIsIHNlcD0iLCIsIGhlYWRlciA9IEYpWyxjKDIsMyldCnJvd25hbWVzKENvb3JkaW5hdGVzKSA8LSByb3duYW1lcyhBUC5kYXRhQG1ldGEuZGF0YSkKQVAuZGF0YSA8LSBTZXREaW1SZWR1Y3Rpb24oQVAuZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVkdWN0aW9uLnR5cGUgPSAic3ByaW5nLkFQIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xvdCA9ICJjZWxsLmVtYmVkZGluZ3MiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBuZXcuZGF0YSA9IGFzLm1hdHJpeChDb29yZGluYXRlcykpCkFQLmRhdGFAZHIkc3ByaW5nLkFQQGtleSA8LSAic3ByaW5nLkFQIgpjb2xuYW1lcyhBUC5kYXRhQGRyJHNwcmluZy5BUEBjZWxsLmVtYmVkZGluZ3MpIDwtIHBhc3RlMChHZXREaW1SZWR1Y3Rpb24ob2JqZWN0ID0gQVAuZGF0YSwgcmVkdWN0aW9uLnR5cGUgPSAic3ByaW5nLkFQIixzbG90ID0gImtleSIpLCBjKDEsMikpCgpgYGAKCiMjIEZpdCBhIHByaW5jaXBhbCBjdXJ2ZSBvdmVyIHRoZSBBUCBpbiB0aGUgU3ByaW5nIHNwYWNlCgpgYGB7cn0KZGF0YSA8LSBkYXRhLmZyYW1lKHNwcmluZ0FQLjEgPSBBUC5kYXRhQGRyJHNwcmluZy5BUEBjZWxsLmVtYmVkZGluZ3NbLDFdLAogICAgICAgICAgICAgICAgICAgc3ByaW5nQVAuMiA9IEFQLmRhdGFAZHIkc3ByaW5nLkFQQGNlbGwuZW1iZWRkaW5nc1ssMl0sCiAgICAgICAgICAgICAgICAgICBzcHJpbmcxID0gQVAuZGF0YUBkciRzcHJpbmdAY2VsbC5lbWJlZGRpbmdzWywxXSwKICAgICAgICAgICAgICAgICAgIHNwcmluZzIgPSBBUC5kYXRhQGRyJHNwcmluZ0BjZWxsLmVtYmVkZGluZ3NbLDJdKQoKIyBGaXQgdGhlIHByaW5jaXBhbCBjdXJ2ZQpmaXQgPC0gcHJpbmNpcGFsX2N1cnZlKGFzLm1hdHJpeChkYXRhWywxOjJdKSwKICAgICAgICAgICAgICAgICAgICAgICBzbW9vdGhlcj0nbG93ZXNzJywKICAgICAgICAgICAgICAgICAgICAgICB0cmFjZT1UUlVFLAogICAgICAgICAgICAgICAgICAgICAgIGYgPSAwLjcsCiAgICAgICAgICAgICAgICAgICAgICAgc3RyZXRjaD0wLAogICAgICAgICAgICAgICAgICAgICAgIHBsb3RfaXRlcmF0aW9ucyA9IEYpCmBgYAoKYGBge3J9CkRvcnNvVmVudHJhbC5TY29yZSA8LSBmaXQkbGFtYmRhL21heChmaXQkbGFtYmRhKSAjVGhlIGFjdHVhbCBzcGV1ZG90aW1lCnBjLmxpbmUgPC0gYXMuZGF0YS5mcmFtZShmaXQkc1tvcmRlcihmaXQkbGFtYmRhKSxdKSAjVGhlIHByaW5jaXBhbCBjdXJ2ZSBzbW9vdGhlZAoKZGF0YSRQaGFzZSA8LSBhcy5jaGFyYWN0ZXIoQVAuZGF0YUBtZXRhLmRhdGEkUGhhc2UpCmRhdGEkRG9yc29WZW50cmFsLlNjb3JlIDwtIERvcnNvVmVudHJhbC5TY29yZQoKIyBEaXJlY3Rpb24gb2YgdGhlIG1hdHVyYXRpb24gc2NvcmUgdXNpbmcgWmJ0YjIwIGV4cHJlc3Npb24gKHJldmVydGUgaWYgcG9zaXRpdmUgY29ycmVsYXRpb24pCmlmIChjb3IoZGF0YSREb3Jzb1ZlbnRyYWwuU2NvcmUsIEFQLmRhdGFAZGF0YVsnWmJ0YjIwJywgXSkgPiAwKSB7IGRhdGEkRG9yc29WZW50cmFsLlNjb3JlIDwtIC0oZGF0YSREb3Jzb1ZlbnRyYWwuU2NvcmUgLSBtYXgoZGF0YSREb3Jzb1ZlbnRyYWwuU2NvcmUpKX0KCkFQLmRhdGFAbWV0YS5kYXRhJERvcnNvVmVudHJhbC5TY29yZSA8LSBkYXRhJERvcnNvVmVudHJhbC5TY29yZQpgYGAKCmBgYHtyIGZpZy5kaW09Yyg1LjMsIDQpfQojUGxvdCBDZWxsIG9udG8gUEMxIGFuZCBQQzIgd2l0aCBwcmluY2lwYWwgY3VydmUKZ2dwbG90KGRhdGEsIGFlcyhzcHJpbmdBUC4xLCBzcHJpbmdBUC4yKSkgKyAKICBnZW9tX3BvaW50KGFlcyhjb2xvcj1QaGFzZSksIHNpemU9Miwgc2hhcGU9MTYsIHZhbHVlcz1jb2wucGFsKSArCiAgZ2VvbV9saW5lKGRhdGE9cGMubGluZSwgY29sb3I9J3JlZCcsIHNpemU9MC43NykKYGBgCgpgYGB7ciBmaWcuZGltPWMoNS4zLCA0KSwgZmlnLmNhcD0gIk1hbnVzY3JpcHQgRmlnLiA1QSJ9CiNQbG90IFNwZXVkb3RpbWUgY29sb3IgZ3JhZGllbnQgb24gdGhlIGNlbGwgY3ljbGUgZmlsdGVyZWQgU3ByaW5nIGVtYmJlZGluZwpnZ3Bsb3QoZGF0YSwgYWVzKHNwcmluZ0FQLjEsIHNwcmluZ0FQLjIpKSArCiAgZ2VvbV9wb2ludChhZXMoY29sb3I9RG9yc29WZW50cmFsLlNjb3JlKSwgc2l6ZT0yLCBzaGFwZT0xNikgKwogIHNjYWxlX2NvbG9yX3ZpcmlkaXMoZGlyZWN0aW9uID0gLTEpICsKICBnZW9tX2xpbmUoZGF0YT1wYy5saW5lLCBjb2xvcj0ncmVkJywgc2l6ZT0wLjc3KQpgYGAKCmBgYHtyIGZpZy5kaW09Yyg1LjMsIDQpfQojUGxvdCBTcGV1ZG90aW1lIGNvbG9yIGdyYWRpZW50IG9uIHRoZSBTcHJpbmcgZW1iYmVkaW5nIGNhbGN1bGF0ZWQgZnJvbSBmdWxsIGRhdGFzZXQKZ2dwbG90KGRhdGEsIGFlcyhzcHJpbmcxLCBzcHJpbmcyKSkgKyAKICBnZW9tX3BvaW50KGFlcyhjb2xvcj1Eb3Jzb1ZlbnRyYWwuU2NvcmUpLCBzaXplPTIsIHNoYXBlPTE2KSArCiAgc2NhbGVfY29sb3JfdmlyaWRpcyhkaXJlY3Rpb24gPSAtMSkgCmBgYAoKIyBGaW5kIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyBhbG9uZyB0aGUgcHNldWRvIERWIGF4aXMKCiMjIEluaXRpYWxpemUgYSBtb25vY2xlIG9iamVjdAoKYGBge3J9CiMgVHJhbnNmZXJ0IG1ldGFkYXRhIAptZXRhLmRhdGEgPC0gZGF0YS5mcmFtZShiYXJjb2RlID0gcm93bmFtZXMoQVAuZGF0YUBtZXRhLmRhdGEpLAogICAgICAgICAgICAgICAgICAgICAgICBDbHVzdGVyID0gQVAuZGF0YUBtZXRhLmRhdGEkb2xkLmlkZW50LAogICAgICAgICAgICAgICAgICAgICAgICBEb3Jzb1ZlbnRyYWwuU2NvcmUgPSAgQVAuZGF0YUBtZXRhLmRhdGEkRG9yc29WZW50cmFsLlNjb3JlLAogICAgICAgICAgICAgICAgICAgICAgICBDZWxsY3ljbGVQaGFzZSA9IEFQLmRhdGFAbWV0YS5kYXRhJFBoYXNlLAogICAgICAgICAgICAgICAgICAgICAgICByb3cubmFtZXMgPSByb3duYW1lcyhBUC5kYXRhQG1ldGEuZGF0YSkpCiAgICAgICAgICAgICAgICAgICAKQW5ub3QuZGF0YSAgPC0gbmV3KCdBbm5vdGF0ZWREYXRhRnJhbWUnLCBkYXRhID0gbWV0YS5kYXRhKQoKIyBUcmFuc2ZlcnQgY291bnQgZGF0YQpjb3VudC5kYXRhID0gZGF0YS5mcmFtZShnZW5lX3Nob3J0X25hbWUgPSByb3duYW1lcyhBUC5kYXRhQHJhdy5kYXRhKSwKICAgICAgICAgICAgICAgICAgcm93Lm5hbWVzID0gcm93bmFtZXMoQVAuZGF0YUByYXcuZGF0YSkpCgpmZWF0dXJlLmRhdGEgPC0gbmV3KCdBbm5vdGF0ZWREYXRhRnJhbWUnLCBkYXRhID0gY291bnQuZGF0YSkKCiMgQ3JlYXRlIHRoZSBDZWxsRGF0YVNldCBvYmplY3QKZ2JtX2NkcyA8LSBuZXdDZWxsRGF0YVNldChhcy5tYXRyaXgoQVAuZGF0YUByYXcuZGF0YSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgcGhlbm9EYXRhID0gQW5ub3QuZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlRGF0YSA9IGZlYXR1cmUuZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICBsb3dlckRldGVjdGlvbkxpbWl0ID0gMSwKICAgICAgICAgICAgICAgICAgICAgICAgICBleHByZXNzaW9uRmFtaWx5ID0gbmVnYmlub21pYWwoKSkKYGBgCgoKYGBge3J9CmdibV9jZHMgPC0gZXN0aW1hdGVTaXplRmFjdG9ycyhnYm1fY2RzKQpnYm1fY2RzIDwtIGVzdGltYXRlRGlzcGVyc2lvbnMoZ2JtX2NkcykKZ2JtX2NkcyA8LSBkZXRlY3RHZW5lcyhnYm1fY2RzLCBtaW5fZXhwciA9IDAuMSkKYGBgCgpgYGB7cn0Kcm0obGlzdCA9IGxzKClbIWxzKCkgJWluJSBjKCJBUC5kYXRhIiwgImdibV9jZHMiKV0pCmBgYAoKIyMgVGVzdCBlYWNoIGdlbmUgdHJlbmQgb3ZlciBwc2V1ZG8tRFYgc2NvcmUKCmBgYHtyfQojIEV4Y2x1ZGUgY2VsbCBjeWNsZSBhc3NvY2lhdGVkIGdlbmVzCkNDZ2VuZXMgPC0gYXMuY2hhcmFjdGVyKHJlYWQudGFibGUoIi4vUHJvZ2VuaXRvcnMvQ2VsbEN5Y2xlR2VuZXMuY3N2Iiwgc2VwID0gIlx0IiwgaGVhZGVyID0gRilbLDFdKQpJbnB1dC5nZW5lcyA8LSBBUC5kYXRhQHZhci5nZW5lc1shQVAuZGF0YUB2YXIuZ2VuZXMgJWluJSBDQ2dlbmVzXQpgYGAKCgpgYGB7cn0KIyBQZXJmb3JtIHRoZSB0ZXN0IGZvciBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBhcyBhIGZ1bmN0aW9uIG9mIHBzZXVkby1EViBzY29yZSB3aGlsZSBjb250cm9saW5nIGZvciBjZWxsIGN5Y2xlIHBoYXNlCkRWLkF4aXMuZ2VuZXMgPC0gZGlmZmVyZW50aWFsR2VuZVRlc3QoZ2JtX2Nkc1tJbnB1dC5nZW5lcyxdLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdWxsTW9kZWxGb3JtdWxhU3RyID0gIn5zbS5ucyhEb3Jzb1ZlbnRyYWwuU2NvcmUsIGRmID0gMykqQ2VsbGN5Y2xlUGhhc2UiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWR1Y2VkTW9kZWxGb3JtdWxhU3RyID0gIn5DZWxsY3ljbGVQaGFzZSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvcmVzID0gZGV0ZWN0Q29yZXMoKSAtMikKCiMgRmlsdGVyIGdlbmVzIHdpdGggYSBGRFIgPCAwLjAwMQpEVi5BeGlzLmdlbmVzLkZEUi5maWx0ZXJlZCA8LSBEVi5BeGlzLmdlbmVzICU+JSBmaWx0ZXIocXZhbCA8IDFlLTMpCmBgYAoKCiMjIFNtb290aCBzaWduaWZpY2F0aXZlIGdlbmUgZXhwcmVzc2lvbiBwc2V1ZG8tRFYgYXhpcwoKYGBge3J9CiMgQ3JlYXRlIGEgbmV3IHBzZXVkby1EViB2ZWN0b3Igb2YgNTAwIHBvaW50cwpuUG9pbnRzIDwtIDUwMApuZXdfZGF0YSA8LSBkYXRhLmZyYW1lKERvcnNvVmVudHJhbC5TY29yZSA9IHNlcShtaW4ocERhdGEoZ2JtX2NkcykkRG9yc29WZW50cmFsLlNjb3JlKSwgbWF4KHBEYXRhKGdibV9jZHMpJERvcnNvVmVudHJhbC5TY29yZSksIGxlbmd0aC5vdXQgPSBuUG9pbnRzKSkKCiMgU21vb3RoIGdlbmUgZXhwcmVzc2lvbgpTbW9vdGguY3VydmUubWF0cml4IDwtIGdlblNtb290aEN1cnZlcyhnYm1fY2RzW2FzLmNoYXJhY3RlcihEVi5BeGlzLmdlbmVzLkZEUi5maWx0ZXJlZCRnZW5lX3Nob3J0X25hbWUpLF0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyZW5kX2Zvcm11bGEgPSAifnNtLm5zKERvcnNvVmVudHJhbC5TY29yZSwgZGYgPSAzKSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbGF0aXZlX2V4cHIgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdfZGF0YSA9IG5ld19kYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3Jlcz0gZGV0ZWN0Q29yZXMoKSAtIDIpCmBgYAoKIyBDbHVzdGVyIGNlbGwgYnkgc2ltaWxhciBleHByZXNzaW9uIHByb2ZpbGVzIG9uIHRoZSBwc2V1ZG8tRFYgYXhpcwoKYGBge3J9CnNldC5zZWVkKDEwMCkKIyBDbHVzdGVyIGNlbGxzIHVzaW5nIHRoZSBQYXJ0aXRpb25pbmcgQXJvdW5kIE1lZG9pZHMgYWxnb3JpdGhtCkNlbGxzLkNsdXN0IDwtIHBhbShhcy5kaXN0KCgxIC0gY29yKFNtb290aC5jdXJ2ZS5tYXRyaXggLG1ldGhvZCA9ICJzcGVhcm1hbiIpKSksIGs9NykKRG9tYWluZXMuQ2x1c3QgPC0gZGF0YS5mcmFtZShEb21haW5lcyA9IHBhc3RlMCgiQ2x1c3QuIixDZWxscy5DbHVzdCRjbHVzdGVyaW5nKSkKYGBgCgojIENsdXN0ZXIgZ2VuZSBieSBzaW1pbGFyIHByb2ZpbGVzIG92ZXIgcHNldWRvLURWIGF4aXMKCiMjIFBlcmZvcm0gaGllcmFyY2hpY2FsIGNsdXN0ZXJpbmcKCmBgYHtyfQojIEJ1aWxkIGdlbmVzIGRlbmRyb2dyYW0KZHN0IDwtIGRpc3QodChzY2FsZSh0KFNtb290aC5jdXJ2ZS5tYXRyaXgpKSksIG1ldGhvZCA9ICJtYW5oYXR0YW4iKQpoYyA8LSBoY2x1c3QoZHN0LCBtZXRob2QgPSAid2FyZC5EIikgIyJ3YXJkLkQiCgojIFNlcmlhdGUgdGhlIGRlbmRyb2dyYW0KZGVuZCA8LSBhcy5kZW5kcm9ncmFtKGhjKQpkZW5kIDwtIGRlbmRleHRlbmQ6OnNlcmlhdGVfZGVuZHJvZ3JhbShkZW5kLCBkc3QsIG1ldGhvZD0iR1ciKQoKIyBGaW5kIDE1IGNsdXN0ZXIgYmFzZWQgb24gaGllcmFyY2hpY2FsIGNsdXN0ZXJpbmcKY2x1c3RlcnMgPC0gY3V0cmVlKGhjLCBrPTEwKQoKR2VuZS5keW5hbWlxdWUgPC0gZGF0YS5mcmFtZShHZW5lPSBuYW1lcyhjbHVzdGVycyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHZhbD0gRFYuQXhpcy5nZW5lcy5GRFIuZmlsdGVyZWQkcHZhbCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBxdmFsPURWLkF4aXMuZ2VuZXMuRkRSLmZpbHRlcmVkJHF2YWwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbnVtX2NlbGxzX2V4cHJlc3NlZD1EVi5BeGlzLmdlbmVzLkZEUi5maWx0ZXJlZCRudW1fY2VsbHNfZXhwcmVzc2VkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIFdhdmVzID0gYXMubnVtZXJpYyhjbHVzdGVycykpICU+JSBhcnJhbmdlKFdhdmVzKQoKcm93Lm5hbWVzKEdlbmUuZHluYW1pcXVlKSA8LSBHZW5lLmR5bmFtaXF1ZSRHZW5lCkdlbmUuZHluYW1pcXVlJEdlbmUuQ2x1c3RlcnMgPC0gcGFzdGUwKCJDbHVzdC4iLEdlbmUuZHluYW1pcXVlJFdhdmVzKQoKd3JpdGUudGFibGUoR2VuZS5keW5hbWlxdWUsICIuL1Byb2dlbml0b3JzL0dlbmUuZHluYW1pcXVlLmNzdiIsIHNlcCA9ICI7IiwgcXVvdGUgPSBGKQpgYGAKCgojIyBQbG90IGdlbmUvY2VsbCBoZWF0bWFwCgpgYGB7ciBmaWcuZGltPWMoNywgOS4zKSwgZmlnLmNhcD0gIk1hbnVzY3JpcHQgRmlnLiA1QyJ9CmFubm8uY29sb3JzIDwtIGxpc3QoRG9tYWluZXMgPSBjKENsdXN0LjE9IiM4M2MzYjgiLCBDbHVzdC4yPSIjMDA5ZmRhIiwgQ2x1c3QuMz0iIzNlNjlhYyIsIENsdXN0LjQ9IiNlNDZiNmIiLCBDbHVzdC41PSIjZTNjMTQ4IiwgQ2x1c3QuNj0iI2I3ZDE3NCIsIENsdXN0Ljc9IiM2OGIwNDEiKSwKICAgICAgICAgICAgICAgICAgICBHZW5lLkNsdXN0ZXJzID0gYyhDbHVzdC4xID0iI2VjNzU2ZCIgLCBDbHVzdC4yPSIjZWJjYjJlIiwgQ2x1c3QuMz0iI2I3OWYwYiIsIENsdXN0LjQ9IiM3MjkzYzgiLCBDbHVzdC41PSIjM2NhNzNmIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDbHVzdC42PSIjOWVjMjJmIiwgQ2x1c3QuNz0iI2NjM2ExYiIsIENsdXN0Ljg9IiM0Y2FiZGMiLCBDbHVzdC45PSIjY2M4Nzc4IiwgQ2x1c3QuMTA9IiM0Nzg0YTIiKSkKCnBoZWF0bWFwOjpwaGVhdG1hcChTbW9vdGguY3VydmUubWF0cml4LAogICAgICAgICAgICAgICAgICAgY2x1c3Rlcl9yb3dzPSBhcy5oY2x1c3QoZGVuZCksCiAgICAgICAgICAgICAgICAgICBzY2FsZSA9ICJyb3ciLAogICAgICAgICAgICAgICAgICAgY2x1c3Rlcl9jb2xzID0gRiwKICAgICAgICAgICAgICAgICAgIGdhcHNfY29sID0gY3Vtc3VtKGFzLm51bWVyaWModGFibGUoRG9tYWluZXMuQ2x1c3QkRG9tYWluZXMpKSksCiAgICAgICAgICAgICAgICAgICBhbm5vdGF0aW9uX3JvdyA9IEdlbmUuZHluYW1pcXVlICU+JSBkcGx5cjo6c2VsZWN0KEdlbmUuQ2x1c3RlcnMpLAogICAgICAgICAgICAgICAgICAgYW5ub3RhdGlvbl9jb2wgPSBEb21haW5lcy5DbHVzdCwKICAgICAgICAgICAgICAgICAgIGFubm90YXRpb25fY29sb3JzID0gYW5uby5jb2xvcnMsCiAgICAgICAgICAgICAgICAgICBzaG93X2NvbG5hbWVzID0gRiwKICAgICAgICAgICAgICAgICAgIHNob3dfcm93bmFtZXMgPSBULAogICAgICAgICAgICAgICAgICAgZm9udHNpemVfcm93ID0gMiwKICAgICAgICAgICAgICAgICAgIGNvbG9yID0gcmV2KGJyZXdlci5wYWwoMTEsIlJkQnUiKSksCiAgICAgICAgICAgICAgICAgICBicmVha3MgPSBzZXEoLTIuNSwyLjUsIGxlbmd0aC5vdXQgPSAxMSksCiAgICAgICAgICAgICAgICAgICBtYWluID0gIkdlbmVzIGV4cHJlc3Npb24gYWxvbmcgRG9yc28tVmVudHJhbCBheGlzIikKYGBgCiMjUGxvdCBnZW5lIGNsdXN0ZXJzIHRyZW5kcwpgYGB7ciBmaWcuZGltPWMoNiwgOSksIGZpZy5jYXA9ICJNYW51c2NyaXB0IEZpZy4gNUMifQpzb3VyY2UoIi4vZnVuY3Rpb25zL0dlbmVzVHJlbmRQbG90cy5SIikKQ2x1c3RlcnMudHJlbmQoQVAuZGF0YSwKICAgICAgICAgICAgICAgV2hpY2guY2x1c3RlciA9IDE6MTAsCiAgICAgICAgICAgICAgIGNsdXN0Lmxpc3QgPSBjbHVzdGVycywKICAgICAgICAgICAgICAgZ3JvdXAuYnkgPSAiZ2xvYmFsIiwKICAgICAgICAgICAgICAgc3BhbiA9IDEsCiAgICAgICAgICAgICAgIFNtb290aC5tZXRob2QgPSAiYXV0byIsCiAgICAgICAgICAgICAgIFVzZS5zY2FsZS5kYXRhID0gVCkKYGBgCgojIyBBc3NpZ24gZG9tYWluIGlkZW50aXR5CgoKV2UgYXNzaWduIGRvbWFpbiBpZGVudGl0eSBiYXNlZCBvbiBjbHVzdGVycycgdHJhbnNjcmlwdGlvbmFsIHByb2ZpbGUgYnkgc2V0dGluZyBib3VuZGFyaWVzIG92ZXIgcHNldWRvLWR2IHNjb3JlCmBgYHtyfQojIFNldCB0aGUgYm91bmRhcnkgb3ZlciBzcGV1ZG90aW1lIHNjb3JlCm5ld19kYXRhJGNsdXN0ZXIgPC0gRG9tYWluZXMuQ2x1c3QkRG9tYWluZXMKSW5mZXJlZC5Eb21haW4uYm91bmRhcnkgPC0gYWdncmVnYXRlKERvcnNvVmVudHJhbC5TY29yZSB+IGNsdXN0ZXIsIG5ld19kYXRhLCBtYXgpICU+JSBwdWxsKERvcnNvVmVudHJhbC5TY29yZSkKCiMgQXNzaWduIGlkZW50aXR5IGJhc2VkIG9uIHRoZSBwb3NpdGlvbiBvZiB0aGUgY2VsbCBvbiB0aGUgcHNldWRvLWR2IGF4aXMKRG9tYWluZS5JZGVudCA8LSBzYXBwbHkoQVAuZGF0YUBtZXRhLmRhdGEkRG9yc29WZW50cmFsLlNjb3JlLAogICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbih4KXsgaWYoeDxJbmZlcmVkLkRvbWFpbi5ib3VuZGFyeVsxXSl7IHggPSAiU3ViLlBhbGxpdW0uMSIKICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmKHg+IEluZmVyZWQuRG9tYWluLmJvdW5kYXJ5WzFdICYgeDwgSW5mZXJlZC5Eb21haW4uYm91bmRhcnlbMl0peyB4ID0iU3ViLlBhbGxpdW0uMiIKICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmKHg+IEluZmVyZWQuRG9tYWluLmJvdW5kYXJ5WzJdICYgeDwgSW5mZXJlZC5Eb21haW4uYm91bmRhcnlbM10peyB4ID0gIlN1Yi5QYWxsaXVtLjMiIAogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYoeD4gSW5mZXJlZC5Eb21haW4uYm91bmRhcnlbM10gJiB4PCBJbmZlcmVkLkRvbWFpbi5ib3VuZGFyeVs0XSl7IHggPSAiVmVudHJhbC5QYWxsaXVtIgogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYoeD4gSW5mZXJlZC5Eb21haW4uYm91bmRhcnlbNF0gJiB4PCBJbmZlcmVkLkRvbWFpbi5ib3VuZGFyeVs1XSl7IHggPSAibGF0ZXJhbC5QYWxsaXVtLjEiCiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZih4PiBJbmZlcmVkLkRvbWFpbi5ib3VuZGFyeVs2XSl7IHggPSAiRG9yc2FsLlBhbGxpdW0iCiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB4PSJsYXRlcmFsLlBhbGxpdW0uMiJ9KQoKIyBUcmFuc2ZlcnQgdGhlIGlkZW50aXR5IHRvIHRoZSBTZXVyYXQgb2JqZWN0CkFQLmRhdGFAbWV0YS5kYXRhJERvbWFpbmUgPC0gRG9tYWluZS5JZGVudApBUC5kYXRhIDwtIFNldEFsbElkZW50KEFQLmRhdGEsIGlkID0gIkRvbWFpbmUiKQpgYGAKCgpgYGB7ciBmaWcuZGltPWMoMTAsNSksIGZpZy5jYXA9ICJNYW51c2NyaXB0IEZpZy4gNUQifQpQbG90LkdlbmVzLnRyZW5kKEFQLmRhdGEsCiAgICAgICAgICAgICAgICAgZ2VuZXMgPSBjKCJHc3gyIiwgIkRieDEiLCAiR20yOTI2MCIsICJUZmFwMmMiLCAiRW14MSIsICJMcnJuMSIpLAogICAgICAgICAgICAgICAgIFVzZS5zY2FsZS5kYXRhID0gRikKYGBgCgpgYGB7ciBmaWcuZGltPWMoNS4zLCA0KX0KRGltUGxvdChBUC5kYXRhLAogICAgICAgICBncm91cC5ieSA9ICJEb21haW5lIiwKICAgICAgICAgcmVkdWN0aW9uLnVzZSA9ICJzcHJpbmciLAogICAgICAgICBkaW0uMSA9IDEsCiAgICAgICAgIGRpbS4yID0gMiwKICAgICAgICAgZG8ubGFiZWw9RiwKICAgICAgICAgbGFiZWwuc2l6ZSA9IDQsCiAgICAgICAgIG5vLmxlZ2VuZCA9IEYsCiAgICAgICAgIGNvbHMudXNlID0gdG9sb3dlcihjKCIjNjhCMDQxIiwgIiNFM0MxNDgiLCAiI0I3RDE3NCIsICIjODNDM0I4IiwgIiMwMDlGREEiLCAiIzNFNjlBQyIsICIjRTQ2QjZCIikpCiAgICAgICAgICkKYGBgCgojIFBsb3QgRmlndXJlIDVCCgpgYGB7cn0KI2xvYWQgZnVsbCBkYXRhc2V0CkFsbGNlbGxzLmRhdGEgPC0gcmVhZFJEUygiLi9RQy5maWx0ZXJlZC5jZWxscy5SRFMiKQoKI1RyYW5zZmVyIHRoZSBpZGVudGl0aWVzClJlbmFtZS5DbHVzdCA8LSAgZnVuY3Rpb24oQ2x1c3RkYXRhLCBSYXdRQ2RhdGEpIHsKICB1bkNsdXN0ZXJlZC5jZWxscyA8LSBSYXdRQ2RhdGFAbWV0YS5kYXRhJEJhcmNvZGVzCiAgUmF3UUNkYXRhIDwtIFNldElkZW50KFJhd1FDZGF0YSwgY2VsbHMudXNlID0gdW5DbHVzdGVyZWQuY2VsbHMsIGlkZW50LnVzZSA9ICJBbGwuVW5jbHVzdGVyZWQuQ2VsbHMiKQogIAogIGZvcihpIGluIHVuaXF1ZShDbHVzdGRhdGFAbWV0YS5kYXRhJERvbWFpbmUpKXsKICBOZXcuaWRlbnQgPC0gaQogIEJhcmNvZGVzIDwtIHJvd25hbWVzKHN1YnNldChDbHVzdGRhdGFAbWV0YS5kYXRhLCBDbHVzdGRhdGFAbWV0YS5kYXRhJERvbWFpbmUgPT0gaSkpCiAgcHJpbnQocGFzdGUwKCJDbHVzdGVyXyIsaSwiOiAiLGxlbmd0aChCYXJjb2RlcyksICIgQ2VsbHMiKSkKICBCYXJjb2RlcyA8LSBCYXJjb2Rlc1tCYXJjb2RlcyAlaW4lIHJvd25hbWVzKFJhd1FDZGF0YUBtZXRhLmRhdGEpXQogIFJhd1FDZGF0YSA8LSBTZXRJZGVudChSYXdRQ2RhdGEsIGNlbGxzLnVzZSA9IEJhcmNvZGVzICxpZGVudC51c2UgPSBwYXN0ZTAoIkFQLiIsaSkpCiAgfQogIHJldHVybihSYXdRQ2RhdGEpCn0KCkFsbGNlbGxzLmRhdGEgPC0gUmVuYW1lLkNsdXN0KENsdXN0ZGF0YSA9IEFQLmRhdGEsIFJhd1FDZGF0YSA9IEFsbGNlbGxzLmRhdGEpCmBgYAoKYGBge3IgZmlnLmRpbT1jKDUuMywgNCksICwgZmlnLmNhcD0gIk1hbnVzY3JpcHQgRmlnLiA1QiJ9CmNvbG9ycyA8LSAgYygiIzk2OTY5NiIsdG9sb3dlcihjKCIjNjhCMDQxIiwgIiNFM0MxNDgiLCAiI0I3RDE3NCIsICIjODNDM0I4IiwgIiMwMDlGREEiLCAiIzNFNjlBQyIsICIjRTQ2QjZCIikpKQoKRGltUGxvdChBbGxjZWxscy5kYXRhLAogICAgICAgIHJlZHVjdGlvbi51c2UgPSAic3ByaW5nIiwgCiAgICAgICAgZGltLjEgPSAxLAogICAgICAgIGRpbS4yID0gMiwKICAgICAgICBkby5sYWJlbD1ULAogICAgICAgIGxhYmVsLnNpemUgPSAyLAogICAgICAgIG5vLmxlZ2VuZCA9IFQsCiAgICAgICAgY29scy51c2UgPSBjb2xvcnMpCmBgYAoKYGBge3J9CnJtKGxpc3QgPSBscygpWyFscygpICVpbiUgYygiQVAuZGF0YSIpXSkKYGBgCgojIFBsb3QgdGhlIHJlcHJlc2VudGF0aXZlIGdlbmUgb2YgdGhlIEZpZ3VyZSBTNgoKYGBge3J9CiMgTG9hZCBjdXN0b20gcGxvdHRpbmcgZnVuY3Rpb25zCnNvdXJjZSgiLi9mdW5jdGlvbnMvR2VuZXNUcmVuZFBsb3RzLlIiKQpgYGAKCiMjIENsdXN0ZXIgNgoKYGBge3IgZmlnLmRpbT1jKDEwLDYpLCBmaWcuY2FwPSAiTWFudXNjcmlwdCBGaWcuUzZBIn0KUGxvdC5HZW5lcy50cmVuZChBUC5kYXRhLAogICAgICAgICAgICAgICAgIGdlbmVzID0gYygiRGx4MSIsICJBbm8xIiwgIkRseDIiLCAiT2xpZzIiKSwKICAgICAgICAgICAgICAgICBVc2Uuc2NhbGUuZGF0YSA9IEYpCmBgYAoKIyMgQ2x1c3RlciAyCgpgYGB7ciBmaWcuZGltPWMoMTAsNiksIGZpZy5jYXA9ICJNYW51c2NyaXB0IEZpZy5TNkIifQpQbG90LkdlbmVzLnRyZW5kKEFQLmRhdGEsCiAgICAgICAgICAgICAgICAgZ2VuZXMgPSBjKCJPdHgyIiwgIlpidGIyMCIsICJTaXgzIiwgIkFzY2wxIiksCiAgICAgICAgICAgICAgICAgVXNlLnNjYWxlLmRhdGEgPSBGKQpgYGAKCiMjIENsdXN0ZXIgMwoKYGBge3IgZmlnLmRpbT1jKDEwLDYpLCBmaWcuY2FwPSAiTWFudXNjcmlwdCBGaWcuUzZDIn0KUGxvdC5HZW5lcy50cmVuZChBUC5kYXRhLAogICAgICAgICAgICAgICAgIGdlbmVzID0gYygiTWVpczEiLCAiUm9yYiIsICJFcGhhMyIpLAogICAgICAgICAgICAgICAgIFVzZS5zY2FsZS5kYXRhID0gRikKYGBgCgojIyBDbHVzdGVyIDEKCmBgYHtyIGZpZy5kaW09YygxMCw2KSwgZmlnLmNhcD0gIk1hbnVzY3JpcHQgRmlnLlM2RCJ9ClBsb3QuR2VuZXMudHJlbmQoQVAuZGF0YSwKICAgICAgICAgICAgICAgICBnZW5lcyA9IGMoIlNmcnAyIiwgIkV2YTFjIiwgIlNlbWE1YSIsICJGYXQ0IiksCiAgICAgICAgICAgICAgICAgVXNlLnNjYWxlLmRhdGEgPSBGKQpgYGAKCiMjIENsdXN0ZXIgOQoKYGBge3IgZmlnLmRpbT1jKDEwLDYpLCBmaWcuY2FwPSAiTWFudXNjcmlwdCBGaWcuUzZFIn0KUGxvdC5HZW5lcy50cmVuZChBUC5kYXRhLAogICAgICAgICAgICAgICAgIGdlbmVzID0gYygiRG1ydGEyIiwiTHlwZDYiLCAiUGF4NiIsICJEbXJ0YTEiKSwKICAgICAgICAgICAgICAgICBVc2Uuc2NhbGUuZGF0YSA9IEYpCmBgYAoKIyMgQ2x1c3RlciA1ID8KCmBgYHtyIGZpZy5kaW09YygxMCw2KSwgZmlnLmNhcD0gIk1hbnVzY3JpcHQgRmlnLlM2RiJ9ClBsb3QuR2VuZXMudHJlbmQoQVAuZGF0YSwKICAgICAgICAgICAgICAgICBnZW5lcyA9IGMoIkVteDEiLCAiQXJ4IiwgIkxtbzMiKSwKICAgICAgICAgICAgICAgICBVc2Uuc2NhbGUuZGF0YSA9IEYpCmBgYAoKIyMgQ2x1c3RlciA5CgpgYGB7ciBmaWcuZGltPWMoMTAsNiksIGZpZy5jYXA9ICJNYW51c2NyaXB0IEZpZy5TNkcifQpQbG90LkdlbmVzLnRyZW5kKEFQLmRhdGEsCiAgICAgICAgICAgICAgICAgZ2VuZXMgPSBjKCJGZXpmMiIsICJFbXgyIiwgIlNwOCIpLAogICAgICAgICAgICAgICAgIFVzZS5zY2FsZS5kYXRhID0gRikKYGBgCgojIFRyYW5zZmVydCB0aGVzZSBpZGVudCBvbiB0aGUgZnVsbCBkYXRhc2V0IChNYW51c2NyaXB0IEZpZy4gMkEpCgpgYGB7cn0KI2xvYWQgZnVsbCBkYXRhc2V0CkFsbGNlbGxzLmRhdGEgPC0gcmVhZFJEUygiLi9DbHVzdGVyZWQuY2VsbHMuUkRTIikKCiNUcmFuc2ZlciB0aGUgaWRlbnRpdGllcwpSZW5hbWUuQ2x1c3QgPC0gIGZ1bmN0aW9uKENsdXN0ZGF0YSwgUmF3UUNkYXRhKSB7CiAgZm9yKGkgaW4gdW5pcXVlKENsdXN0ZGF0YUBtZXRhLmRhdGEkRG9tYWluZSkpewogICAgTmV3LmlkZW50IDwtIGkKICAgIEJhcmNvZGVzIDwtIHJvd25hbWVzKHN1YnNldChDbHVzdGRhdGFAbWV0YS5kYXRhLCBDbHVzdGRhdGFAbWV0YS5kYXRhJERvbWFpbmUgPT0gaSkpCiAgICBwcmludChwYXN0ZTAoIkNsdXN0ZXJfIixpLCI6ICIsbGVuZ3RoKEJhcmNvZGVzKSwgIiBDZWxscyIpKQogICAgQmFyY29kZXMgPC0gQmFyY29kZXNbQmFyY29kZXMgJWluJSByb3duYW1lcyhSYXdRQ2RhdGFAbWV0YS5kYXRhKV0KICAgIFJhd1FDZGF0YSA8LSBTZXRJZGVudChSYXdRQ2RhdGEsIGNlbGxzLnVzZSA9IEJhcmNvZGVzICxpZGVudC51c2UgPSBwYXN0ZTAoIkFQLiIsaSkpCiAgfQogIHJldHVybihSYXdRQ2RhdGEpCn0KCkFsbGNlbGxzLmRhdGEgPC0gUmVuYW1lLkNsdXN0KENsdXN0ZGF0YSA9IEFQLmRhdGEsIFJhd1FDZGF0YSA9IEFsbGNlbGxzLmRhdGEpCmBgYAoKYGBge3IgZmlnLmRpbT1jKDgsIDYpLCBmaWcuY2FwPSAiTWFudXNjcmlwdCBGaWcuIDJBIn0KY29sb3JzMiA8LSAgYygiIzk2OTY5NiIsCiAgICAgICAgICAgICAgdG9sb3dlcihjKCIjNjhCMDQxIiwgIiNFM0MxNDgiLCAiI0I3RDE3NCIsICIjODNDM0I4IiwgIiMwMDlGREEiLCAiIzNFNjlBQyIsICIjRTQ2QjZCIikpLAogICAgICAgICAgICAgICIjZWM3NTZkIiwgIiNjNzczYTciLCAiIzcyOTNjOCIsICIjYjc5ZjBiIiwgIiMzY2E3M2YiLCIjMzFiNmJkIiwKICAgICAgICAgICAgICAiI2ViY2IyZSIsICIjOWVjMjJmIiwgIiNhOTk2MWIiLCAiI2NjM2ExYiIsICIjY2M4Nzc4IiAsICIjZDE0YzhkIiwgIiM0Y2FiZGMiLCAiIzVhYjc5MyIsICIjZTc4MjNhIiwiI2U2YmI5YiIsICIjMDQ2YzlhIiwgIiM0Nzg0YTIiICwgIiM0OTkwYzkiKQoKRGltUGxvdChBbGxjZWxscy5kYXRhLAogICAgICAgIHJlZHVjdGlvbi51c2UgPSAic3ByaW5nIiwgCiAgICAgICAgZGltLjEgPSAxLAogICAgICAgIGRpbS4yID0gMiwKICAgICAgICBkby5sYWJlbD1ULAogICAgICAgIGxhYmVsLnNpemUgPSAyLAogICAgICAgIG5vLmxlZ2VuZCA9IFQsCiAgICAgICAgY29scy51c2UgPSBjb2xvcnMyKQpgYGAKCmBgYHtyfQpBbGxjZWxscy5kYXRhIDwtIFN0YXNoSWRlbnQoQWxsY2VsbHMuZGF0YSwgc2F2ZS5uYW1lID0gIkNsdXN0ZXIuaWRlbnQiKQpzYXZlUkRTKEFsbGNlbGxzLmRhdGEsICIuL0NsdXN0ZXJlZC5jZWxscy5SRFMiKQpzYXZlUkRTKEFQLmRhdGEsICIuL0FQLmRhdGEuUkRTIikKYGBgCgojIFNlc3Npb24gSW5mbwpgYGB7cn0KI2RhdGUKZm9ybWF0KFN5cy50aW1lKCksICIlZCAlQiwgJVksICVILCVNIikKCiNQYWNrYWdlcyB1c2VkCnNlc3Npb25JbmZvKCkKYGBg